import SparkMD5 from 'spark-md5'
import { uploadChunk, checkChunk, checkFile, mergeChunk } from '@/api/system'

// 目前问题：fileUrl因为异步无法返回（得到的是undefined）
// 来个东哥修改一下
// 走红已修改，我下次在研究

// 文件上传工具类
const CHRUNK_SIZE = 1024 * 1024 * 5 //分片大小
const MAX_REQUEST_NUM = 4
let activePromises = []
let progress = 0
//大文件上传文件
export const customRequest = async (op, onProgress) => {
  const file = op.fileItem.file
  const chunks = createChunk(file)
  const fileMd5 = await calcHash(chunks)
  // console.log('fileMd5', fileMd5)
  const fileUrl = await uploadChunks(file.name, chunks, fileMd5, MAX_REQUEST_NUM, onProgress)
  return fileUrl
}
// 创建分片
const createChunk = (file) => {
  let cur = 0
  let chunks = []
  while (cur < file.size) {
    const blob = file.slice(cur, cur + CHRUNK_SIZE)
    chunks.push(blob)
    cur += CHRUNK_SIZE
  }
  return chunks
}
//计算hash
const calcHash = (chunks) => {
  const targets = []
  let md5
  const spark = new SparkMD5.ArrayBuffer()
  const fileReader = new FileReader()
  // 为了计算hash更快，截取部分文件片
  chunks.forEach((chunck, index) => {
    if (index === 0 || index === chunks.length - 1) {
      targets.push(chunck)
    } else {
      targets.push(chunck.slice(0, 2))
      targets.push(chunck.slice(CHRUNK_SIZE / 2, CHRUNK_SIZE / 2 + 2))
      targets.push(chunck.slice(CHRUNK_SIZE - 2, CHRUNK_SIZE))
    }
  })
  // 好扭比的普绕米斯 令我文件上传爆肥
  return new Promise((resolve, reject) => {
    fileReader.readAsArrayBuffer(new Blob(targets))

    fileReader.onload = (e) => {
      spark.append(e.target.result)
      const md5 = spark.end()
      resolve(md5) // 成功时返回md5值
    }

    fileReader.onerror = (err) => {
      reject(err) // 失败时抛出错误
    }
  })
}
// 分片上传
const uploadChunks = async (fileName, chunks, fileMd5, MAX_REQUEST_NUM = 4, onProgress) => {
  const formDatas = chunks.map((chunk, index) => {
    const formData = new FormData()
    formData.append('fileName', fileName)
    formData.append('fileMd5', fileMd5)
    formData.append('chunkMd5', `${fileMd5}-${index}`)
    formData.append('chunk', chunk)
    return formData
  })
  for (let i = 0; i < formDatas.length; i++) {
    await uploadNext(i, formDatas[i], formDatas.length, onProgress)
    if (i >= formDatas.length - 1) {
      // 所有分片都已上传
      await Promise.all(activePromises) // 等待所有剩余的活动 Promise 完成（理论上应该是空的）
      // 合并分片
      const mergeChunkDto = { fileName, fileMd5 }
      const fileUrl = await mergeChunk(mergeChunkDto)
      console.log('合并后的url:', fileUrl)
      return fileUrl
    }
  }
}

const uploadNext = async (i, formData, maxLength, onProgress) => {
  const promise = uploadChunk(formData).finally(() => {
    // 从活动 Promise 数组中移除这个 Promise
    const indexToRemove = activePromises.findIndex((p) => p === promise)
    if (indexToRemove !== -1) {
      activePromises.splice(indexToRemove, 1)
    }
    // 上传完成后更新进度条
    progress = Math.round(((i + 1) / maxLength) * 100).toFixed(2)
    if (onProgress) {
      onProgress(progress)
    }
  })
  // 将这个 Promise 添加到活动 Promise 数组中
  activePromises.push(promise)
  if (activePromises.length > MAX_REQUEST_NUM) {
    await Promise.race(activePromises.map((p) => p.finally(() => false)))
  }
}
